

#include <iostream>
#include <wchar.h>
#include "Parser.h"
#include "Scanner.h"




void Parser::SynErr(int n) {
	if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n);
	errDist = 0;
}

void Parser::SemErr(const wchar_t* msg) {
	if (errDist >= minErrDist) errors->Error(t->line, t->col, msg);
	errDist = 0;
}

void Parser::Get() {
	for (;;) {
		t = la;
		la = scanner->Scan();
		if (la->kind <= maxT) { ++errDist; break; }

		if (dummyToken != t) {
			dummyToken->kind = t->kind;
			dummyToken->pos = t->pos;
			dummyToken->col = t->col;
			dummyToken->line = t->line;
			dummyToken->next = NULL;
			coco_string_delete(dummyToken->val);
			dummyToken->val = coco_string_create(t->val);
			t = dummyToken;
		}
		la = t;
	}
}

void Parser::Expect(int n) {
	if (la->kind==n) Get(); else { SynErr(n); }
}

void Parser::ExpectWeak(int n, int follow) {
	if (la->kind == n) Get();
	else {
		SynErr(n);
		while (!StartOf(follow)) Get();
	}
}

bool Parser::WeakSeparator(int n, int syFol, int repFol) {
	if (la->kind == n) {Get(); return true;}
	else if (StartOf(repFol)) {return false;}
	else {
		SynErr(n);
		while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) {
			Get();
		}
		return StartOf(syFol);
	}
}

void Parser::EON() {
		while (la->kind == 11) {
			ClassDeclaration();
		}
		StatementSequence();
		Expect(0);
}

void Parser::ClassDeclaration() {
		SymTableEntry entry; 
		Expect(11);
		Ident(entry.name);
		Expect(12);
		Statement();
		while (StartOf(1)) {
			Statement();
		}
		Expect(13);
}

void Parser::StatementSequence() {
		Statement();
		while (StartOf(1)) {
			Statement();
		}
}

void Parser::Ident(char *name) {
		name = NULL; 
		Expect(1);
}

void Parser::Statement() {
		if (StartOf(2)) {
			if (la->kind == 16) {
				VarDeclaration();
			} else if (la->kind == 1) {
				Assignment();
			} else {
				Directive();
			}
			Expect(9);
		} else if (la->kind == 20 || la->kind == 22 || la->kind == 24) {
			BlockStatement();
		} else SynErr(43);
}

void Parser::VarDeclaration() {
		SymTableEntry entry; ASTNode * V; 
		Expect(16);
		Variable(V);
		Expect(17);
		rhs();
}

void Parser::Assignment() {
		ASTNode * V; 
		Variable(V);
		SymTableEntry entry; 
		Expect(17);
		rhs();
}

void Parser::Directive() {
		if (la->kind == 14) {
			Get();
			Expect(8);
		} else if (la->kind == 15) {
			Get();
			Expect(8);
		} else SynErr(44);
}

void Parser::BlockStatement() {
		if (la->kind == 20) {
			IfConditional();
		} else if (la->kind == 22) {
			WhileConditional();
		} else if (la->kind == 24) {
			ForeachLoop();
		} else SynErr(45);
}

void Parser::Variable(ASTNode * &V) {
		SymTableEntry entry; 
		Designator(V,(int)SymIDClass::vars,entry,true);
}

void Parser::rhs() {
		ASTNode * exp; char str[62]; 
		if (la->kind == 2) {
			int val; 
			Number(val);
		} else if (la->kind == 7) {
			String(str);
		} else if (StartOf(3)) {
			Expression(exp,true);
		} else SynErr(46);
}

void Parser::Designator(ASTNode * &D, classset allowed, SymTableEntry & entry, bool entire) {
		char	name[32]; ASTNode * idx, sz; bool found; 
		D = compiler->EmptyAST(); 
		Ident(name);
		Expect(18);
		Expression(idx,true);
		Expect(19);
}

void Parser::Expression(ASTNode * &E,bool entire) {
		ASTNode * T; opers op;
		E = compiler->EmptyAST(); 
		if (la->kind == 28) {
			Get();
			Term(E,true);
		} else if (la->kind == 26) {
			Get();
			Term(E,true);
		} else if (StartOf(4)) {
			Term(E,true);
		} else SynErr(47);
		while (la->kind == 26 || la->kind == 28) {
			AddSubOp(op);
			Term(T,true);
			compiler->BinaryIntOp(op,E,T); 
		}
}

void Parser::Number(int &num) {
		char buf[7]; 
		Expect(2);
		num = StringToInt(buf); 
}

void Parser::String(char * str) {
		Expect(7);
		char buf[128]; 
		strcpy(str,buf); 
}

void Parser::IfConditional() {
		ASTNode * C; 
		Expect(20);
		Condition(C);
		Expect(12);
		StatementSequence();
		Expect(13);
		if (la->kind == 21) {
			Get();
			Expect(12);
			StatementSequence();
			Expect(13);
		}
}

void Parser::WhileConditional() {
		ASTNode * C; 
		Expect(22);
		Condition(C);
		Expect(12);
		Statement();
		if (la->kind == 23) {
			Get();
			Expect(9);
		}
		while (StartOf(1)) {
			Statement();
		}
		Expect(13);
}

void Parser::ForeachLoop() {
		SymTableEntry entry; int from,to; 
		Expect(24);
		Ident(entry.name);
		Expect(25);
		if (la->kind == 1) {
			Ident(entry.name);
		} else if (la->kind == 18) {
			Get();
			if (la->kind == 26) {
				Get();
			}
			Number(from);
			Expect(27);
			if (la->kind == 26) {
				Get();
			}
			Number(to);
			Expect(19);
		} else SynErr(48);
		Expect(12);
		Statement();
		if (la->kind == 23) {
			Get();
			Expect(9);
		}
		while (StartOf(1)) {
			Statement();
		}
		Expect(13);
}

void Parser::Condition(ASTNode * &C) {
		ASTNode * E; opers op; 
		Expression(C,true);
		RelOp(op);
		Expression(E,true);
}

void Parser::RelOp(opers &op) {
		switch (la->kind) {
		case 36: {
			Get();
			op = opers::eq; 
			break;
		}
		case 37: {
			Get();
			op = opers::neq; 
			break;
		}
		case 38: {
			Get();
			op = opers::lt; 
			break;
		}
		case 39: {
			Get();
			op = opers::gt; 
			break;
		}
		case 40: {
			Get();
			op = opers::lteq; 
			break;
		}
		case 41: {
			Get();
			op = opers::gteq; 
			break;
		}
		default: SynErr(49); break;
		}
}

void Parser::Term(ASTNode * &T, bool entire) {
		ASTNode * F; opers op; 
		Factor(T,entire);
		while (StartOf(5)) {
			if (la->kind == 34 || la->kind == 35) {
				MultDivOp(op);
			} else {
				op = opers::mult; 
			}
			Factor(F,true);
			compiler->BinaryIntOp(op,T,F); 
		}
}

void Parser::AddSubOp(opers &op) {
		if (la->kind == 28) {
			Get();
			op = opers::add; 
		} else if (la->kind == 26) {
			Get();
			op = opers::sub; 
		} else SynErr(50);
}

void Parser::Factor(ASTNode * &F,bool entire) {
		if (la->kind == 1) {
			SymTableEntry entry; int val; F = compiler->EmptyAST(); 
			Designator(F,((int)SymIDClass::consts|(int)SymIDClass::vars|(int)SymIDClass::funcs),entry,entire);
			switch (entry.idclass) {
			case SymIDClass::consts:
				break;
			default:
				return;
			} 
			Number(val);
		} else if (la->kind == 29) {
			Get();
		} else if (la->kind == 30) {
			Get();
		} else if (la->kind == 31) {
			Get();
			Factor(F,true);
		} else if (la->kind == 32) {
			Get();
			Expression(F,true);
			Expect(33);
		} else SynErr(51);
}

void Parser::MultDivOp(opers &op) {
		if (la->kind == 34) {
			Get();
			op = opers::mult; 
		} else if (la->kind == 35) {
			Get();
			op = opers::div; 
		} else SynErr(52);
}



void Parser::Parse() {
	t = NULL;
	la = dummyToken = new Token();
	la->val = coco_string_create(L"Dummy Token");
	Get();
	EON();

	Expect(0);
}

Parser::Parser(Scanner *scanner) {
	maxT = 42;

	dummyToken = NULL;
	t = la = NULL;
	minErrDist = 2;
	errDist = minErrDist;
	this->scanner = scanner;
	errors = new Errors();
}

bool Parser::StartOf(int s) {
	const bool T = true;
	const bool x = false;

	static bool set[6][44] = {
		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
		{x,T,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, T,x,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
		{x,T,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
		{x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x},
		{x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x},
		{x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,T,T, x,x,x,x, x,x,x,x}
	};



	return set[s][la->kind];
}

Parser::~Parser() {
	delete errors;
	delete dummyToken;
}

Errors::Errors() {
	count = 0;
}

void Errors::SynErr(int line, int col, int n) {
	wchar_t* s;
	switch (n) {
			case 0: s = coco_string_create(L"EOF expected"); break;
			case 1: s = coco_string_create(L"ident expected"); break;
			case 2: s = coco_string_create(L"uint expected"); break;
			case 3: s = coco_string_create(L"binnum expected"); break;
			case 4: s = coco_string_create(L"hexnum expected"); break;
			case 5: s = coco_string_create(L"float expected"); break;
			case 6: s = coco_string_create(L"char expected"); break;
			case 7: s = coco_string_create(L"string expected"); break;
			case 8: s = coco_string_create(L"pkg expected"); break;
			case 9: s = coco_string_create(L"terminate expected"); break;
			case 10: s = coco_string_create(L"EOL expected"); break;
			case 11: s = coco_string_create(L"\"module\" expected"); break;
			case 12: s = coco_string_create(L"\"{\" expected"); break;
			case 13: s = coco_string_create(L"\"}\" expected"); break;
			case 14: s = coco_string_create(L"\"import\" expected"); break;
			case 15: s = coco_string_create(L"\"package\" expected"); break;
			case 16: s = coco_string_create(L"\"new\" expected"); break;
			case 17: s = coco_string_create(L"\"<-\" expected"); break;
			case 18: s = coco_string_create(L"\"[\" expected"); break;
			case 19: s = coco_string_create(L"\"]\" expected"); break;
			case 20: s = coco_string_create(L"\"if\" expected"); break;
			case 21: s = coco_string_create(L"\"else\" expected"); break;
			case 22: s = coco_string_create(L"\"while\" expected"); break;
			case 23: s = coco_string_create(L"\"leave\" expected"); break;
			case 24: s = coco_string_create(L"\"foreach\" expected"); break;
			case 25: s = coco_string_create(L"\"in\" expected"); break;
			case 26: s = coco_string_create(L"\"-\" expected"); break;
			case 27: s = coco_string_create(L"\"..\" expected"); break;
			case 28: s = coco_string_create(L"\"+\" expected"); break;
			case 29: s = coco_string_create(L"\"True\" expected"); break;
			case 30: s = coco_string_create(L"\"False\" expected"); break;
			case 31: s = coco_string_create(L"\"!\" expected"); break;
			case 32: s = coco_string_create(L"\"(\" expected"); break;
			case 33: s = coco_string_create(L"\")\" expected"); break;
			case 34: s = coco_string_create(L"\"*\" expected"); break;
			case 35: s = coco_string_create(L"\"/\" expected"); break;
			case 36: s = coco_string_create(L"\"==\" expected"); break;
			case 37: s = coco_string_create(L"\"!=\" expected"); break;
			case 38: s = coco_string_create(L"\"<\" expected"); break;
			case 39: s = coco_string_create(L"\">\" expected"); break;
			case 40: s = coco_string_create(L"\"<=\" expected"); break;
			case 41: s = coco_string_create(L"\">=\" expected"); break;
			case 42: s = coco_string_create(L"??? expected"); break;
			case 43: s = coco_string_create(L"invalid Statement"); break;
			case 44: s = coco_string_create(L"invalid Directive"); break;
			case 45: s = coco_string_create(L"invalid BlockStatement"); break;
			case 46: s = coco_string_create(L"invalid rhs"); break;
			case 47: s = coco_string_create(L"invalid Expression"); break;
			case 48: s = coco_string_create(L"invalid ForeachLoop"); break;
			case 49: s = coco_string_create(L"invalid RelOp"); break;
			case 50: s = coco_string_create(L"invalid AddSubOp"); break;
			case 51: s = coco_string_create(L"invalid Factor"); break;
			case 52: s = coco_string_create(L"invalid MultDivOp"); break;

		default:
		{
			wchar_t format[20];
			coco_swprintf(format, 20, L"error %d", n);
			s = coco_string_create(format);
		}
		break;
	}
	wprintf(L"-- line %d col %d: %ls\n", line, col, s);
	coco_string_delete(s);
	count++;
}

void Errors::Error(int line, int col, const wchar_t *s) {
	wprintf(L"-- line %d col %d: %ls\n", line, col, s);
	count++;
}

void Errors::Warning(int line, int col, const wchar_t *s) {
	wprintf(L"-- line %d col %d: %ls\n", line, col, s);
}

void Errors::Warning(const wchar_t *s) {
	wprintf(L"%ls\n", s);
}

void Errors::Exception(const wchar_t* s) {
	wprintf(L"%ls", s); 
	exit(1);
}



